home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume23 / xmodem3.9 / part01 next >
Encoding:
Internet Message Format  |  1991-01-08  |  52.5 KB

  1. Subject:  v23i077:  Xmodem file transfer program, revision3.9, Part01/03
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 02329e80 c9389d8c ced0b526 9fb92597
  5.  
  6. Submitted-by: Steve Grandi <grandi@noao.edu>
  7. Posting-number: Volume 23, Issue 77
  8. Archive-name: xmodem3.9/part01
  9.  
  10. The xmodem program implements the Christensen (XMODEM) file transfer
  11. protocol for moving files between 4.2/4.3BSD Unix systems (and successors,
  12. including Suns) and microcomputers.  The XMODEM/CRC protocol, the MODEM7
  13. batch protocol, the XMODEM-1K block protocol, the YMODEM batch protocol
  14. and the YMODEM-G streaming protocol are all supported by xmodem.  The
  15. ZMODEM protocol is not supported.
  16.  
  17. This is version 3.9 (circa 11/90) of the xmodem program which incorporates
  18. a few bugfixes (one important!) and some enhancements: 1) status messages
  19. when running xmodem through Sun's tip program ("p" flag); 2) delayed
  20. startup (via the "w" flag); 3) ability to turn off EOT verification (via
  21. "e" flag); 4) ability to allow CAN-CAN abort in the midst of a file
  22. transfer (via "n"  flag) and 5) YMODEM-G support (via the "g" flag).  See
  23. update.doc for details. 
  24.  
  25. #! /bin/sh
  26. # This is a shell archive.  Remove anything before this line, then feed it
  27. # into a shell via "sh file" or similar.  To overwrite existing files,
  28. # type "sh file -c".
  29. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  30. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  31. # Contents:  README Makefile receive.c xmodem.c
  32. # Wrapped by rsalz@litchi.bbn.com on Wed Dec  5 12:31:56 1990
  33. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  34. echo If this archive is complete, you will see the following message:
  35. echo '          "shar: End of archive 1 (of 3)."'
  36. if test -f 'README' -a "${1}" != "-c" ; then 
  37.   echo shar: Will not clobber existing file \"'README'\"
  38. else
  39.   echo shar: Extracting \"'README'\" \(21493 characters\)
  40.   sed "s/^X//" >'README' <<'END_OF_FILE'
  41. XThis is version 3.9 (circa 11/90) of the xmodem program which incorporates
  42. Xa few bugfixes (one important!) and some enhancements: 1) status messages
  43. Xwhen running xmodem through Sun's tip program ("p" flag); 2) delayed
  44. Xstartup (via the "w" flag); 3) ability to turn off EOT verification (via
  45. X"e" flag); 4) ability to allow CAN-CAN abort in the midst of a file
  46. Xtransfer (via "n"  flag) and 5) YMODEM-G support (via the "g" flag).  See
  47. Xupdate.doc for details. 
  48. X
  49. X--------------------------------------------------------------------------------
  50. X
  51. XThis is version 3.8 (circa 11/88) of the xmodem program which incorporates
  52. Xminor enhancements over version 3.7 which incoporates minor enhancements
  53. Xover version 3.6.  See update.doc. 
  54. X
  55. X--------------------------------------------------------------------------------
  56. X
  57. XThis is version 3.6 (finished 4/88) of the xmodem program which includes a
  58. Xfew bugfixes and some enhancements (requested by Macintosh users)
  59. Xstimulated by the xmodem release through comp.sources.unix.  See the file
  60. Xupdate.doc for details. 
  61. X
  62. X--------------------------------------------------------------------------------
  63. X
  64. XThis is version 3.4 (finished 10/87) of the xmodem program, a full-featured
  65. XXMODEM implementation for 4.3BSD.  Since the previous release (version
  66. X3.2, see volume 7 of the archives), substantial improvements have been
  67. Xmade. See the file update.doc for details.  Also, some attempt has been
  68. Xmade to support SysV Unix systems; see below.
  69. X
  70. XAs far as I am concerned, this program has reached the end of its evolution.
  71. XNewer protocols (such as ZMODEM) will not be incorporated into xmodem.  Check
  72. Xout Chuck Forsberg's rz/sz programs if you are interested in ZMODEM.
  73. X
  74. X--------------------------------------------------------------------------------
  75. X
  76. XThe xmodem program implements the Christensen (XMODEM) file transfer
  77. Xprotocol for moving files between 4.2/4.3BSD Unix systems and microcomputers.
  78. XThe XMODEM/CRC protocol, the MODEM7 batch protocol, the XMODEM-1K
  79. Xblock protocol and the YMODEM batch protocol are all supported by xmodem.
  80. XFor details of the protocols, see the document edited by Chuck Forsberg titled
  81. XXMODEM/YMODEM Protocol Reference (the latest version is dated 6-18-88).
  82. X
  83. XThis program runs on 4.2/4.3BSD systems ONLY.  It has been tested on VAXes
  84. Xand Suns against the MEX-PC program from Niteowl Software and the ZCOMM and
  85. XDSZ programs from Omen Technology.
  86. X
  87. XI have tried to keep the 4.2isms (select system call, 4.2BSD/v7 tty structures,
  88. Xgettimeofday system call, etc.) confined to the source file getput.c; but I 
  89. Xmake no guarantees.  Also, I have made no attempt to keep variable names 
  90. Xunder 7 characters.  A version of getput.c that MAY work on Sys V Unix
  91. Xsystems is included.
  92. X
  93. X--------------------------------------------------------------------------------
  94. X
  95. XThanks to Emmet Gray (ihnp4!uiucuxc!fthood!egray) and John Rupley 
  96. X(arizona!rupley!root) for the following notes about converting xmodem to Sys V.
  97. XSince I don't have a Sys V system to test a Sys V version, I won't even try.
  98. X
  99. X1) Change the includes in xmodem.h from <sys/time.h> to <time.h>
  100. X   and from <sgtty.h> to <termio.h>
  101. X
  102. X2) Convert the occurrences of rindex to strrchr in batch.c
  103. X
  104. X3) Substitute getput.sysv.c for getput.c
  105. X
  106. XA further "gotcha" regarding Sys V is contained in the following message :
  107. X
  108. XFrom: Bill Stubblebine <hplsdls!was@hp-lsd.UUCP>
  109. XDate: Sat, 25 Jun 88 13:36:20 mdt
  110. XTo: grandi@noao.arizona.edu
  111. XSubject: xmodem3.6 bug, fix and THANKS!!
  112. X
  113. X                        1:30 PM MDT
  114. X                        June 25, 1988
  115. X
  116. XFirst, thanks for posting a really useful program, xmodem 3.6.
  117. X
  118. XI installed the xmodem program on an HP 9000 Series 350 workstation,
  119. Xrunning HP-UX version 6.01 (AT&T System V compatible) to talk to my
  120. XCP/M system at home.  MODEM7 batch is particularly useful.
  121. X
  122. XI'd like to report a bug I found and the fix I developed in the source
  123. Xfile getput.sysv.c so that you can include it in future releases.
  124. X
  125. XI've reproduced the relevant portion of getput.sysv.c, modified to fix
  126. Xthe bug, at the end of this file.  See the routine getspeed() starting
  127. Xat line 382.  Getspeed() derives the serial port speed from the
  128. Xc_cflag ioctl parameter, for use in estimating transmission times.
  129. X
  130. XI suspected something was wrong when xmodem kept reporting 1200 baud
  131. Xmodem connections as 1800 baud in the log file, but the transfers
  132. Xstill worked OK at 1200 baud.  However, I also have a Courier HST 9600
  133. Xbaud modem at home, and when I tried 9600 baud xmodem transfers,
  134. Xxmodem would core dump on the UNIX host.
  135. X
  136. XOn line 386 of getput.sysv.c, in the procedure getspeed(), an array is
  137. Xdeclared containing numerical constants representing the various baud
  138. Xrates supported by the host terminal interface.  The appropriate baud
  139. Xrate constant is selected by the statements in lines 392-394, which
  140. Xmask the c_cflag baud rate bitfield to index into the speedtbl[]
  141. Xarray.
  142. X
  143. XThere are two problems here.  The first problem is that speedtbl[] is
  144. Xmissing some valid baud rate entries, as the modified declaration
  145. Xshows.  I got the entries for the modified declaration from the
  146. Xtermio(7) manpage in my System V user's manual.  The missing entries
  147. Xthrow off the indexing arithmetic.  Notice, for example, that the
  148. Xmissing entry 900 was responsible for mapping the c_cflag bits for
  149. X1200 baud to the 1800 baud constant.
  150. X
  151. XOriginal declaration:
  152. X  static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
  153. X  1200, 1800, 2400, 4800, 9600, 19200, 0};
  154. X
  155. XModified declaration:
  156. X  static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
  157. X  900, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 0};
  158. X  ^^^                    ^^^^        ^^^^        ^^^^^  ^^^^^
  159. X
  160. XThe second problem didn't show up until I used 9600 baud.  The c_cflag
  161. Xbitfield value for 9600 baud is 16 decimal (020 octal).  The masking
  162. Xconstant in lines 392-394 was originally 017 octal, which masked the
  163. X9600 baud bitfield to 0, indexing to the speedtbl[] value of 0.  Speed
  164. Xcalculations using a baudrate of 0 caused floating point exceptions
  165. Xleading to the host core dumps at 9600 baud.
  166. X
  167. XI changed the mask value from 017 octal to 037 octal (which is
  168. Xactually the size of the c_cflag baudrate field), and changed the
  169. Xlimit test in line 392 from 14 to 18, the new correct number of
  170. Xelements in the speedtbl[] array.
  171. X
  172. XI'm not familiar with 4.2BSD, but I noticed that getput.c, the 4.2BSD
  173. Xversion of the I/O routines, contains virtually the same code for
  174. Xdetermining the baudrate as that in getput.sysv.c.  It may be OK for
  175. X4.2BSD, but definitely not for System V.
  176. X
  177. XThe modified code now works great at all baud rates!  Thanks again for
  178. Xposting the program.
  179. X
  180. X                                Bill Stubblebine
  181. X                                Hewlett-Packard Logic Systems Div.
  182. X                8245 N. Union Blvd.
  183. X                                Colorado Springs, Co. 80918
  184. X                ARPA: was%hp-lsd@hplabs.hp.com
  185. X                UUCP: {hplabs,hpfcla}!{hpldola,hp-lsd}!was
  186. X
  187. X--------------------------------------------------------------------------------
  188. X
  189. XA common request to me concerns running xmodem through tip in order to do
  190. XXMODEM or YMODEM transfers.  I have discovered that SunOS has a nice
  191. Xfeature in tip (accessed through ~C) that connects a named program to a
  192. Xremote machine.  It turns out that 4.3BSD tip has a similar (but
  193. Xundocumented) feature, but far less convenient: SunOS tip connects file
  194. Xdescriptor 0 of the program to the remote line input and file descriptor 1
  195. Xto remote line output while 4.3BSD connects up file descriptors 3 and 4! 
  196. X
  197. XIf you would like to use xmodem through 4.3BSD tip, the following message
  198. Xshould be of interest (note that the patches given below are against an old
  199. Xversion of the source):
  200. X
  201. XTo: grandi@noao.edu (Steve Grandi CCS)
  202. XSubject: Re: xmodem 
  203. XDate: Tue, 02 Jan 90 12:34:58 -0500
  204. XFrom: Benson I. Margulies <benson@odi.com>
  205. X
  206. X
  207. X    Yes, I would like to receive the changes!
  208. X
  209. X    Steve, grandi@noao.edu
  210. X
  211. XOK, here are the diffs. I've tested them in receive mode,
  212. Xbut I haven't been able to verify that they work for sending.
  213. XThe reason why is a long sob story.
  214. X
  215. XIt would be good to do two additional things:
  216. X
  217. X1) add some \r's to the messages printed.
  218. X2) when in tip mode, print more messages on stdout
  219. Xto report progress, like a . every 100 blocks.
  220. X
  221. XRCS file: RCS/xmodem.c,v
  222. Xretrieving revision 1.1
  223. Xretrieving revision 1.2
  224. Xdiff -c -r1.1 -r1.2
  225. X*** /tmp/,RCSt1a02154    Tue Jan  2 12:33:12 1990
  226. X--- /tmp/,RCSt2a02154    Tue Jan  2 12:33:12 1990
  227. X***************
  228. X*** 52,57 ****
  229. X--- 52,60 ----
  230. X      MDM7BAT = FALSE;    /* no MODEM7 batch mode */
  231. X      YMDMBAT = FALSE;    /* no YMODEM batch mode */
  232. X      TOOBUSY = FALSE;    /* not too busy for sleeping in packet read */
  233. X+     INFD = 0;
  234. X+     OUTFD = 1;
  235. X+     FDS_DISTINCT = 0;
  236. X  
  237. X      fprintf(stderr, "XMODEM Version %d.%d", VERSION/10, VERSION%10);
  238. X      fprintf(stderr, " -- UNIX-Microcomputer Remote File Transfer Facility\n");
  239. X***************
  240. X*** 101,106 ****
  241. X--- 104,115 ----
  242. X          case 's' : SENDFLAG = TRUE;  /* send file */
  243. X                 XMITTYPE = gettype(argv[1][index++]);
  244. X                 break;
  245. X+         case 'p':  /* TIP */
  246. X+         case 'P':
  247. X+                    INFD = 3;
  248. X+                OUTFD = 4;
  249. X+                FDS_DISTINCT = TRUE;
  250. X+                break;
  251. X          default  : fprintf(stderr, "Invalid Flag %c ignored\n", flag);
  252. X                 break;
  253. X         }
  254. X***************
  255. X*** 120,133 ****
  256. X          LOGFP = fopen(fname, "w");  /* new LOG file */
  257. X           if (!LOGFP)
  258. X          error("Fatal - Can't Open Log File", FALSE);
  259. X  
  260. X           fprintf(LOGFP,"\n++++++++  %s", stamptime());
  261. X           fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
  262. X           fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
  263. X!          for (index=2; index<argc; ++index)
  264. X!         fprintf(LOGFP, " %s", argv[index]);
  265. X           fprintf(LOGFP, "\n");
  266. X!        }
  267. X  
  268. X      getspeed();        /* get tty-speed for time estimates */
  269. X  
  270. X--- 129,147 ----
  271. X          LOGFP = fopen(fname, "w");  /* new LOG file */
  272. X           if (!LOGFP)
  273. X          error("Fatal - Can't Open Log File", FALSE);
  274. X+          setlinebuf(LOGFP);
  275. X  
  276. X           fprintf(LOGFP,"\n++++++++  %s", stamptime());
  277. X+          
  278. X           fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
  279. X+ 
  280. X           fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
  281. X! 
  282. X!          for (index=2; index<argc; ++index) {
  283. X!          fprintf(LOGFP, " %s", argv[index]);
  284. X!          }
  285. X           fprintf(LOGFP, "\n");
  286. X!      }
  287. X  
  288. X      getspeed();        /* get tty-speed for time estimates */
  289. X  
  290. X===================================================================
  291. XRCS file: RCS/xmodem.h,v
  292. Xretrieving revision 1.1
  293. Xretrieving revision 1.2
  294. Xdiff -c -r1.1 -r1.2
  295. X*** /tmp/,RCSt1a02154    Tue Jan  2 12:33:13 1990
  296. X--- /tmp/,RCSt2a02154    Tue Jan  2 12:33:14 1990
  297. X***************
  298. X*** 10,16 ****
  299. X  #define  logit(string) if(LOGFLAG)fprintf(LOGFP,string)
  300. X  #define  logitarg(string,argument) if(LOGFLAG)fprintf(LOGFP,string,argument)
  301. X  
  302. X! #define         VERSION    36    /* Version Number */
  303. X  #define      FALSE      0
  304. X  #define      TRUE       1
  305. X  
  306. X--- 10,16 ----
  307. X  #define  logit(string) if(LOGFLAG)fprintf(LOGFP,string)
  308. X  #define  logitarg(string,argument) if(LOGFLAG)fprintf(LOGFP,string,argument)
  309. X  
  310. X! #define         VERSION    37    /* Version Number */
  311. X  #define      FALSE      0
  312. X  #define      TRUE       1
  313. X  
  314. X***************
  315. X*** 73,78 ****
  316. X--- 73,81 ----
  317. X  int    YMDMBAT;    /* YMODEM batch protocol */
  318. X  int    TOOBUSY;    /* turn off sleeping in packet read routine */
  319. X  int    CHECKLENGTH;    /* Are we truncating a file to a YMODEM length? */
  320. X+ int     INFD;        /* file descriptor for protocol reading */
  321. X+ int    OUTFD;        /* file descriptor for protocol reading */
  322. X+ int     FDS_DISTINCT;   /* in,out fd's not 0 and 1 */
  323. X  
  324. X  
  325. X  /*   CRC-16 constants.  From Usenet contribution by Mark G. Mendel, 
  326. X===================================================================
  327. XRCS file: RCS/getput.c,v
  328. Xretrieving revision 1.1
  329. Xretrieving revision 1.2
  330. Xdiff -c -r1.1 -r1.2
  331. X*** /tmp/,RCSt1a02154    Tue Jan  2 12:33:14 1990
  332. X--- /tmp/,RCSt2a02154    Tue Jan  2 12:33:15 1990
  333. X***************
  334. X*** 4,9 ****
  335. X--- 4,10 ----
  336. X   */
  337. X  
  338. X  #include "xmodem.h"
  339. X+ #include <sys/types.h>
  340. X  
  341. X  /*
  342. X   *
  343. X***************
  344. X*** 103,113 ****
  345. X  /* get a byte from data stream -- timeout if "seconds" elapses */
  346. X  /* This routine is VERY 4.2 specific */
  347. X  
  348. X  int
  349. X  readbyte(seconds)
  350. X  int seconds;
  351. X      {
  352. X-     int readfd;
  353. X      char c;
  354. X      struct timeval tmout;
  355. X  
  356. X--- 104,122 ----
  357. X  /* get a byte from data stream -- timeout if "seconds" elapses */
  358. X  /* This routine is VERY 4.2 specific */
  359. X  
  360. X+ int select_input (tmout)
  361. X+ struct timeval * tmout;
  362. X+ {
  363. X+     fd_set readfd;        /* mask for select call */
  364. X+     FD_ZERO(&readfd);
  365. X+     FD_SET(INFD, &readfd);
  366. X+     return select(getdtablesize(), &readfd, (int *)0, (int *)0, tmout);
  367. X+ }
  368. X+ 
  369. X  int
  370. X  readbyte(seconds)
  371. X  int seconds;
  372. X      {
  373. X      char c;
  374. X      struct timeval tmout;
  375. X  
  376. X***************
  377. X*** 114,125 ****
  378. X      tmout.tv_sec = seconds;
  379. X      tmout.tv_usec = 0;
  380. X  
  381. X-     readfd = 1<<0;
  382. X  
  383. X!     if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  384. X!         return(TIMEOUT);
  385. X  
  386. X!     read(0, &c, 1);
  387. X  
  388. X      if (DEBUG)
  389. X          fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
  390. X--- 123,133 ----
  391. X      tmout.tv_sec = seconds;
  392. X      tmout.tv_usec = 0;
  393. X  
  394. X  
  395. X!     if (select_input(&tmout) == 0)
  396. X!         return(TIMEOUT);
  397. X  
  398. X!     read(INFD, &c, 1);
  399. X  
  400. X      if (DEBUG)
  401. X          fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
  402. X***************
  403. X*** 138,151 ****
  404. X      /* set up a usec timeout on stdin */
  405. X      tmout.tv_sec = 0;
  406. X      tmout.tv_usec = 1;
  407. X!     readfd = 1<<0;
  408. X  
  409. X      /* any characters pending?; return if none */
  410. X!     if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  411. X!         return;
  412. X  
  413. X      /* read the characters to flush them (assume there are fewer than BBUFSIZ */
  414. X!     (void) read(0, inbuf, BBUFSIZ);
  415. X      }
  416. X--- 146,159 ----
  417. X      /* set up a usec timeout on stdin */
  418. X      tmout.tv_sec = 0;
  419. X      tmout.tv_usec = 1;
  420. X!     readfd = 1<<INFD;
  421. X  
  422. X      /* any characters pending?; return if none */
  423. X!     if (select_input(&tmout) == 0)
  424. X!         return;
  425. X  
  426. X      /* read the characters to flush them (assume there are fewer than BBUFSIZ */
  427. X!     (void) read(INFD, inbuf, BBUFSIZ);
  428. X      }
  429. X***************
  430. X*** 170,181 ****
  431. X  long recvsectcnt;    /* running sector count (128 byte sectors) */
  432. X  
  433. X  {
  434. X-     int readfd;        /* mask for select call */
  435. X-     struct timeval tmout;    /* timeout structure for select */
  436. X      int numread;        /* number of chars read */
  437. X      int left;        /* number of chars left to read */
  438. X      int recfin = FALSE;        /* flag that EOF read */
  439. X      char inbuf[BBUFSIZ];    /* buffer for incoming packet */
  440. X      register unsigned char c;    /* character being processed */
  441. X      register unsigned short chksm;    /* working copy of checksum */
  442. X      register int bfctr;    /* working copy of bufctr */
  443. X--- 178,188 ----
  444. X  long recvsectcnt;    /* running sector count (128 byte sectors) */
  445. X  
  446. X  {
  447. X      int numread;        /* number of chars read */
  448. X      int left;        /* number of chars left to read */
  449. X      int recfin = FALSE;        /* flag that EOF read */
  450. X      char inbuf[BBUFSIZ];    /* buffer for incoming packet */
  451. X+     struct timeval tmout;    /* timeout structure for select */
  452. X      register unsigned char c;    /* character being processed */
  453. X      register unsigned short chksm;    /* working copy of checksum */
  454. X      register int bfctr;    /* working copy of bufctr */
  455. X***************
  456. X*** 184,190 ****
  457. X  
  458. X      tmout.tv_sec = seconds;
  459. X      tmout.tv_usec = 0;
  460. X-     readfd = 1<<0;
  461. X      chksm = 0;
  462. X      bfctr = 0;
  463. X  
  464. X--- 191,196 ----
  465. X***************
  466. X*** 192,201 ****
  467. X  
  468. X          /* read however many chars are waiting */
  469. X  
  470. X!         if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  471. X!             return(TIMEOUT);
  472. X  
  473. X!         numread = read(0, inbuf, left);
  474. X          left -= numread;
  475. X  
  476. X          if (DEBUG)
  477. X--- 198,207 ----
  478. X  
  479. X          /* read however many chars are waiting */
  480. X  
  481. X!         if (select_input(&tmout) == 0)
  482. X!             return(TIMEOUT);
  483. X  
  484. X!         numread = read(INFD, inbuf, left);
  485. X          left -= numread;
  486. X  
  487. X          if (DEBUG)
  488. X***************
  489. X*** 275,281 ****
  490. X      if (DEBUG)
  491. X          fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
  492. X  
  493. X!     if (write(1, &data, 1) != 1)      /* write the byte (assume it goes NOW; no flushing needed) */
  494. X          error ("Write error on stream", TRUE);
  495. X      return;
  496. X      }
  497. X--- 281,287 ----
  498. X      if (DEBUG)
  499. X          fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
  500. X  
  501. X!     if (write(OUTFD, &data, 1) != 1)      /* write the byte (assume it goes NOW; no flushing needed) */
  502. X          error ("Write error on stream", TRUE);
  503. X      return;
  504. X      }
  505. X***************
  506. X*** 289,295 ****
  507. X      if (DEBUG)
  508. X          fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
  509. X  
  510. X!     if (write(1, buffer, nbytes) != nbytes)        /* write the buffer (assume no TIOCFLUSH needed) */
  511. X          error ("Write error on stream", TRUE);
  512. X      return;
  513. X      }
  514. X--- 295,301 ----
  515. X      if (DEBUG)
  516. X          fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
  517. X  
  518. X!     if (write(OUTFD, buffer, nbytes) != nbytes)        /* write the buffer (assume no TIOCFLUSH needed) */
  519. X          error ("Write error on stream", TRUE);
  520. X      return;
  521. X      }
  522. X***************
  523. X*** 302,308 ****
  524. X  int    milliseconds;
  525. X  {
  526. X      struct    timeval    timeout;
  527. X-     int readfd;
  528. X  
  529. X      if (milliseconds == 0)
  530. X          return;
  531. X--- 308,313 ----
  532. X***************
  533. X*** 310,318 ****
  534. X          fprintf (LOGFP, "DEBUG: napping for %d ms\n", milliseconds);
  535. X      timeout.tv_sec = 0;
  536. X      timeout.tv_usec = milliseconds * 1000;
  537. X-     readfd = 0;
  538. X  
  539. X!     (void) select(1, &readfd, (int *)0, (int *)0, &timeout);
  540. X  }
  541. X--- 315,322 ----
  542. X          fprintf (LOGFP, "DEBUG: napping for %d ms\n", milliseconds);
  543. X      timeout.tv_sec = 0;
  544. X      timeout.tv_usec = milliseconds * 1000;
  545. X  
  546. X!     (void) select(0, (int *)0, (int *)0, (int *)0, &timeout);
  547. X  }
  548. X***************
  549. X*** 335,344 ****
  550. X      extern onintr();
  551. X  
  552. X      sleep(2);            /* let the output appear */
  553. X!     if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
  554. X          error("Can't get TTY Parameters", TRUE);
  555. X  
  556. X!     tty = ttyname(0);  /* identify current tty */
  557. X      
  558. X      ttysnew.sg_ispeed = ttys.sg_ispeed;    /* copy input speed */
  559. X      ttysnew.sg_ospeed = ttys.sg_ospeed;    /* copy input speed */
  560. X--- 339,348 ----
  561. X      extern onintr();
  562. X  
  563. X      sleep(2);            /* let the output appear */
  564. X!     if (ioctl(INFD,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
  565. X          error("Can't get TTY Parameters", TRUE);
  566. X  
  567. X!     tty = ttyname(INFD);  /* identify current tty */
  568. X      
  569. X      ttysnew.sg_ispeed = ttys.sg_ispeed;    /* copy input speed */
  570. X      ttysnew.sg_ospeed = ttys.sg_ospeed;    /* copy input speed */
  571. X***************
  572. X*** 347,358 ****
  573. X      ttysnew.sg_flags &= ~TANDEM;    /* turn off flow control */
  574. X  
  575. X      /* set new paramters */
  576. X!     if (ioctl(0,TIOCSETP,&ttysnew) < 0)
  577. X          error("Can't set new TTY Parameters", TRUE);
  578. X  
  579. X      /* Flush characters waiting for read or write */
  580. X      n = 0;
  581. X!     if (ioctl(0,TIOCFLUSH,&n) < 0)
  582. X          error("Can't flush terminal queue", TRUE);
  583. X  
  584. X      /* get tty status */ 
  585. X--- 351,362 ----
  586. X      ttysnew.sg_flags &= ~TANDEM;    /* turn off flow control */
  587. X  
  588. X      /* set new paramters */
  589. X!     if (ioctl(INFD,TIOCSETP,&ttysnew) < 0)
  590. X          error("Can't set new TTY Parameters", TRUE);
  591. X  
  592. X      /* Flush characters waiting for read or write */
  593. X      n = 0;
  594. X!     if (ioctl(INFD,TIOCFLUSH,&n) < 0)
  595. X          error("Can't flush terminal queue", TRUE);
  596. X  
  597. X      /* get tty status */ 
  598. X***************
  599. X*** 381,387 ****
  600. X      if (wason)
  601. X          if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
  602. X              error("Can't change TTY mode", FALSE);
  603. X!     if (ioctl(0,TIOCSETP,&ttys) < 0)
  604. X          { if (!errcall)
  605. X             error("RESET - Can't restore normal TTY Params", FALSE);
  606. X          else
  607. X--- 385,391 ----
  608. X      if (wason)
  609. X          if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
  610. X              error("Can't change TTY mode", FALSE);
  611. X!     if (ioctl(INFD,TIOCSETP,&ttys) < 0)
  612. X          { if (!errcall)
  613. X             error("RESET - Can't restore normal TTY Params", FALSE);
  614. X          else
  615. X***************
  616. X*** 423,429 ****
  617. X      {
  618. X      static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 
  619. X         1200, 1800, 2400, 4800, 9600, 19200, 0};
  620. X!     if (ioctl(0,TIOCGETP,&ttys) < 0)    /* get tty structure */
  621. X          error("Can't get TTY parameters", FALSE);
  622. X  
  623. X      if (ttys.sg_ispeed >= 0 && ttys.sg_ispeed <= 14)
  624. X--- 427,433 ----
  625. X      {
  626. X      static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 
  627. X         1200, 1800, 2400, 4800, 9600, 19200, 0};
  628. X!     if (ioctl(INFD,TIOCGETP,&ttys) < 0)    /* get tty structure */
  629. X          error("Can't get TTY parameters", FALSE);
  630. X  
  631. X      if (ttys.sg_ispeed >= 0 && ttys.sg_ispeed <= 14)
  632. X
  633. X--------------------------------------------------------------------------------
  634. X
  635. Xxmodem Program history:
  636. X
  637. XDescended from UMODEM 3.5 by Lauren Weinstein, Richard Conn, and others.
  638. X
  639. XBased on XMODEM Version 1.0 by Brian Kantor, UCSD (3/84)  (Don't blame him 
  640. X    in any way for what follows....)
  641. X
  642. XVersion 2.0 (CRC-16 and Modem7 batch file transfer) (5/85) (Thanks to D'Anne
  643. X    Thompson for the batch transfer code).
  644. X
  645. XVersion 2.1 (1K packets) (7/85)
  646. X
  647. XVersion 2.2 (general clean-ups and multi-character read speed-ups) (9/85)
  648. X
  649. XVersion 2.3 (nap while reading packets; split into several source files) (1/86)
  650. X
  651. XVersion 3.0 (Ymodem batch receive; associated changes) (2/86)
  652. X
  653. XVersion 3.1 (Ymodem batch send; associated changes) (8/86)
  654. X
  655. XVersion 3.2 (general cleanups) (9/86) 
  656. X    (Released to the world 1/87)
  657. X
  658. XVersion 3.3 (general fixes and cleanups; see update.doc) (5/87)
  659. X
  660. XVersion 3.4 (general fixes and cleanups; see update.doc) (10/87) 
  661. X    (Released to the world 3/88)
  662. X
  663. XVersion 3.5 (general fixes and cleanups; see update.doc) (3/88)
  664. X
  665. XVersion 3.6 (general fixes and cleanups; text file translation for Mac; 
  666. X    see update.doc) (4/88) 
  667. X    (Released to the world 4/88)
  668. X
  669. XVersion 3.7 (general fixes and cleanups; see update.doc) (5/88)
  670. X
  671. XVersion 3.8 (general fixes and cleanups; see update.doc) (11/88)
  672. X
  673. XVersion 3.9 (general fixes and cleanups; Sun tip support; 
  674. X    see update.doc) (11/90)
  675. X
  676. X--------------------------------------------------------------------------------
  677. X
  678. XPlease send bug fixes, additions and comments to:
  679. XSteve Grandi, National Optical Astronomy Observatories (Tucson, Arizona, USA)
  680. X    grandi@noao.edu
  681. END_OF_FILE
  682.   if test 21493 -ne `wc -c <'README'`; then
  683.     echo shar: \"'README'\" unpacked with wrong size!
  684.   fi
  685.   # end of 'README'
  686. fi
  687. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  688.   echo shar: Will not clobber existing file \"'Makefile'\"
  689. else
  690.   echo shar: Extracting \"'Makefile'\" \(914 characters\)
  691.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  692. XOBJECTS = xmodem.o getput.o misc.o send.o receive.o batch.o
  693. XCFLAGS = -O
  694. X
  695. Xxmodem: $(OBJECTS)
  696. X    cc $(CFLAGS) $(OBJECTS) -o xmodem
  697. X
  698. X$(OBJECTS): xmodem.h
  699. X
  700. Xprint: 
  701. X    lpr -p -Pvmslp xmodem.h xmodem.c getput.c receive.c send.c batch.c \
  702. X    misc.c Makefile update.doc README xmodem.1 getput.sysv.c
  703. X
  704. Xlint:
  705. X    lint xmodem.c getput.c receive.c send.c batch.c misc.c | imprint
  706. X
  707. Xshar:
  708. X    shar README Makefile xmodem.1 xmodem.h > xmodem.shar.1
  709. X    shar update.doc xmodem.c receive.c > xmodem.shar.2
  710. X    shar getput.c getput.sysv.c > xmodem.shar.3
  711. X    shar misc.c batch.c send.c > xmodem.shar.4
  712. X    shar ymodem.doc > xmodem.shar.5
  713. X
  714. Xbigshar: 
  715. X    shar README update.doc Makefile xmodem.1 xmodem.h xmodem.c getput.c \
  716. X    getput.sysv.c receive.c misc.c batch.c send.c > xmodem.shar
  717. X
  718. Xtarz: 
  719. X    tar cvf xmodem.tar README update.doc Makefile xmodem.1 xmodem.h \
  720. X    xmodem.c getput.c getput.sysv.c receive.c misc.c batch.c send.c \
  721. X    ymodem.doc
  722. X    compress xmodem.tar
  723. END_OF_FILE
  724.   if test 914 -ne `wc -c <'Makefile'`; then
  725.     echo shar: \"'Makefile'\" unpacked with wrong size!
  726.   fi
  727.   # end of 'Makefile'
  728. fi
  729. if test -f 'receive.c' -a "${1}" != "-c" ; then 
  730.   echo shar: Will not clobber existing file \"'receive.c'\"
  731. else
  732.   echo shar: Extracting \"'receive.c'\" \(17709 characters\)
  733.   sed "s/^X//" >'receive.c' <<'END_OF_FILE'
  734. X#include "xmodem.h"
  735. X
  736. X/**  receive a file  **/
  737. X
  738. X/* returns TRUE if in the midst of a batch transfer */
  739. X/* returns FALSE if no more files are coming */
  740. X
  741. X/* This routine is one HUGE do-while loop with far to many indented levels.
  742. X * I chose this route to facilitate error processing and to avoid GOTOs.
  743. X * Given the troubles I've had keeping the nested IF statements straight,
  744. X * I was probably mistaken...
  745. X */
  746. X
  747. Xrfile(name)
  748. Xchar *name;
  749. X{
  750. X
  751. Xchar *sectdisp();
  752. Xchar *cpm_unix();
  753. Xchar *strcpy();
  754. Xchar *ctime();
  755. Xtime_t time();
  756. X
  757. Xint fd,     /* file descriptor for created file */
  758. Xchecksum,   /* packet checksum */
  759. Xfirstchar,  /* first character of a packet */
  760. Xsectnum,    /* number of last received packet (modulo 128) */
  761. Xsectcurr,   /* second byte of packet--should be packet number (mod 128) */
  762. Xsectcomp,   /* third byte of packet--should be complement of sectcurr */
  763. Xtmode,      /* text mode if true */
  764. Xamode,      /* apple mode if true */
  765. Xerrors,     /* count of errors for each packet */
  766. Xsterrors,   /* count of errors during startup handshake */
  767. Xerrorflag,  /* set true when packet (or first char of putative packet) is invalid */
  768. Xfatalerror, /* set within main "read-packet" Do-While when bad error found */
  769. Xinchecksum, /* incoming checksum or CRC */
  770. Xexpsect,    /* expected number of sectors (YMODEM batch) */
  771. Xfirstwait,  /* seconds to wait for first character in a packet */
  772. Xnocancanabort, /* if true, don't allow CAN-CAN abort */
  773. Xbufsize;    /* packet size (128 or 1024) */
  774. Xlong recvsectcnt;   /* running sector count (128 byte sectors) */
  775. Xlong modtime;       /* Unix style file mod time from YMODEM header */
  776. Xint filemode;       /* Unix style file mode from YMODEM header */
  777. Xint serial;    /* serial # from YMODEM header */
  778. Xint filesleft;        /* # of files left from YMODEM header */
  779. Xlong totalleft;        /* # of bytes left from YMODEM header */
  780. Xint yfiletype;        /* file type from YMODEM header */
  781. Xlong readbackup;    /* "backup" value for characters read in file */
  782. Xtime_t timep[2];    /* used in setting mod time of received file */
  783. Xchar *p;    /* generic pointer */
  784. Xint bufctr; /* number of real chars in read packet */
  785. Xunsigned char *nameptr; /* ptr in filename for MODEM7 protocol */
  786. Xtime_t start;       /* starting time of transfer */
  787. Xint openflag = FALSE;   /* is file open for writing? */
  788. X
  789. Xlogit("----\nXMODEM File Receive Function\n");
  790. Xtlogit("----\nXMODEM File Receive Function\n");
  791. Xif (CRCMODE)
  792. X    {
  793. X    logit("CRC mode requested on command line\n");
  794. X    tlogit("CRC mode requested on command line\n");
  795. X    }
  796. X
  797. Xif (YMODEMG)
  798. X    {
  799. X    logit("YMODEM-G mode requested on command line\n");
  800. X    tlogit("YMODEM-G mode requested on command line\n");
  801. X    }
  802. X
  803. XBATCH = FALSE;          /* don't know if really are in batch mode ! */
  804. Xfatalerror = FALSE;
  805. Xfirstwait = WAITFIRST;  /* For first packet, wait short time */
  806. Xsectnum = errors = recvsectcnt = 0;
  807. Xbufsize = 128;
  808. Xmodtime = 0l; filemode = 0;
  809. Xserial = 0; filesleft = 0; totalleft = 0l; yfiletype = 0;
  810. Xfilelength = 0l; fileread =0l; CHECKLENGTH = FALSE;
  811. Xnocancanabort = FALSE;
  812. X
  813. Xtmode = (XMITTYPE == 't') ? TRUE : FALSE;
  814. Xamode = (XMITTYPE == 'a') ? TRUE : FALSE;
  815. X
  816. X/* start up transfer */
  817. X
  818. Xsterrors = 0;
  819. Xflushin();         /* flush input queue */
  820. X
  821. Xif (YMODEMG)
  822. X    sendbyte(GCHR);
  823. Xelse if (CRCMODE && !MDM7BAT)        
  824. X{
  825. X    sendbyte(CRCCHR);
  826. X    if (LONGPACK && !MDM7BAT)
  827. X        sendbyte(KCHR);
  828. X}
  829. Xelse
  830. X    sendbyte(NAK);
  831. X
  832. X
  833. Xdo                  /* start of MAIN Do-While loop to read packets */
  834. X{   
  835. X    errorflag = FALSE;
  836. X    do              /* start by reading first byte in packet */
  837. X    {
  838. X        firstchar = readbyte(firstwait);
  839. X    } 
  840. X    while ((firstchar != SOH) 
  841. X        && (firstchar != STX) 
  842. X        && (firstchar != EOT) 
  843. X        && (firstchar != ACK || recvsectcnt > 0) 
  844. X        && (firstchar != TIMEOUT) 
  845. X        && (firstchar != CAN || nocancanabort));
  846. X
  847. X    if (firstchar == EOT && !NOEOT)           /* check for REAL EOT */
  848. X    {
  849. X        flushin();
  850. X        sendbyte(NAK);              /* NAK the EOT */
  851. X        if ((firstchar = readbyte(5)) != EOT)   /* check next character */
  852. X        {
  853. X            logit("Spurious EOT detected; ignored\n");
  854. X            tlogit("Spurious EOT detected; ignored\n");
  855. X            if ((firstchar == SOH) || (firstchar == STX) ||
  856. X                (firstchar == ACK && recvsectcnt == 0) ||
  857. X                (firstchar == CAN && !nocancanabort) ||
  858. X                (firstchar == TIMEOUT))
  859. X                ;
  860. X            else
  861. X            {
  862. X                firstchar = 0;
  863. X                errorflag = TRUE;
  864. X            }
  865. X        }
  866. X    }
  867. X
  868. X    if (firstchar == TIMEOUT)       /* timeout? */
  869. X    {  
  870. X        if (recvsectcnt > 0)
  871. X            {
  872. X            logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
  873. X            tlogitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
  874. X            }
  875. X        errorflag = TRUE;
  876. X    }
  877. X
  878. X    if (firstchar == CAN)           /* bailing out? (only at beginning or if CANCAN flag set) */
  879. X    {
  880. X        if ((readbyte(3) & 0x7f) == CAN)
  881. X            {
  882. X            if (openflag)
  883. X                {
  884. X                close(fd);
  885. X                unlink(name);
  886. X                error("Reception Canceled by CAN-CAN; partial file deleted",TRUE);
  887. X                }
  888. X            else
  889. X                error("Reception Canceled by CAN-CAN",TRUE);
  890. X            }
  891. X        else
  892. X        {
  893. X            errorflag = TRUE;
  894. X            logit("Received single CAN character\n");
  895. X            tlogit("Received single CAN character\n");
  896. X        }
  897. X    }
  898. X
  899. X    if (firstchar == ACK)           /* MODEM7 batch? (only at beginning) */
  900. X    {
  901. X        int i,c; 
  902. X
  903. X        logit("MODEM7 Batch Protocol\n");
  904. X        tlogit("MODEM7 Batch Protocol\n");
  905. X        nameptr = buff;
  906. X        checksum = 0;
  907. X
  908. X        for (i=0; i<NAMSIZ; i++)
  909. X        {
  910. X            c = readbyte(3);
  911. X
  912. X            if (c == CAN)
  913. X            {
  914. X                if (readbyte(3) == CAN)
  915. X                    error("Program Canceled by CAN-CAN", TRUE);
  916. X                else
  917. X                {
  918. X                    logit("Received single CAN character in MODEM7 filename\n");
  919. X                    tlogit("Received single CAN character in MODEM7 filename\n");
  920. X                    errorflag = TRUE;
  921. X                    break;
  922. X                }
  923. X            }
  924. X
  925. X            if (c == EOT && i == 0)
  926. X            {
  927. X                sendbyte(ACK);          /* acknowledge EOT */
  928. X                logit("MODEM7 Batch Receive Complete\n");
  929. X                tlogit("MODEM7 Batch Receive Complete\n");
  930. X                return (FALSE);
  931. X            }
  932. X
  933. X            if (c == TIMEOUT)
  934. X            {
  935. X                logit("Timeout waiting for MODEM7 filename character\n");
  936. X                tlogit("Timeout waiting for MODEM7 filename character\n");
  937. X                errorflag = TRUE;
  938. X                break;
  939. X            }
  940. X
  941. X            if (c == BAD_NAME)
  942. X            {
  943. X                logit("Error during MODEM7 filename transfer\n");
  944. X                tlogit("Error during MODEM7 filename transfer\n");
  945. X                errorflag = TRUE;
  946. X                break;
  947. X            }
  948. X
  949. X            *nameptr++ = c;
  950. X            checksum += c;
  951. X            sendbyte(ACK);
  952. X        }
  953. X
  954. X        if (!errorflag)
  955. X        {
  956. X            c = readbyte(3);
  957. X            if (c == CTRLZ)     /* OK; end of string found */
  958. X            {
  959. X                sendbyte(checksum + CTRLZ);
  960. X                if (readbyte(15) == ACK)     /* file name found! */
  961. X                {
  962. X                    xmdebug("MODEM7 file name OK");
  963. X                    *nameptr = '\000';  /* unixify the file name */
  964. X                    name = cpm_unix(buff);
  965. X                    BATCH = TRUE;
  966. X                    logitarg("MODEM7 file name: %s\n", name);
  967. X                    tlogitarg("MODEM7 file name: %s\n", name);
  968. X                    errors = 0;     /* restart crc handshake */
  969. X                    sleep(2);       /* give other side a chance */
  970. X                }
  971. X                else
  972. X                {
  973. X                    logit("Checksum error in MODEM7 filename\n");
  974. X                    tlogit("Checksum error in MODEM7 filename\n");
  975. X                    errorflag = TRUE;
  976. X                }
  977. X            }
  978. X            else
  979. X            {
  980. X                logit("Length error in MODEM7 filename\n");
  981. X                tlogit("Length error in MODEM7 filename\n");
  982. X                errorflag = TRUE;
  983. X            }
  984. X        }
  985. X    }
  986. X
  987. X
  988. X    if (firstchar == SOH || firstchar == STX)  /* start reading packet */
  989. X    {
  990. X        bufsize = (firstchar == SOH) ? 128 : 1024;
  991. X
  992. X        if (recvsectcnt == 0)           /* 1st data packet, initialize */
  993. X        {
  994. X            if (bufsize == 1024)
  995. X                {
  996. X                logit("1K packet mode chosen\n");
  997. X                tlogit("1K packet mode chosen\n");
  998. X                }
  999. X            start = time((time_t *) 0);
  1000. X            errors = 0;
  1001. X            firstwait = 5;
  1002. X        }
  1003. X
  1004. X        sectcurr = readbyte(3);
  1005. X        sectcomp = readbyte(3);
  1006. X        if ((sectcurr + sectcomp) == 0xff)  /* is packet number checksum correct? */
  1007. X        {  
  1008. X            if (sectcurr == ((sectnum+1) & 0xff))   /* is packet number correct? */
  1009. X            {  
  1010. X                if (DEBUG)
  1011. X                    fprintf(LOGFP,"DEBUG: packet with sector number %d started\n", sectnum);
  1012. X
  1013. X                /* Read, process and calculate checksum for a buffer of data */
  1014. X
  1015. X                readbackup = fileread;
  1016. X                if (readbuf(bufsize, 1, tmode, amode, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
  1017. X                {
  1018. X
  1019. X                    /* verify checksum or CRC */
  1020. X
  1021. X                    if (CRCMODE) 
  1022. X                    {
  1023. X                        checksum &= 0xffff;
  1024. X                        inchecksum = readbyte(3);  /* get 16-bit CRC */
  1025. X                        inchecksum = (inchecksum<<8) | readbyte(3);
  1026. X                    }
  1027. X
  1028. X                    else
  1029. X                        inchecksum = readbyte(3);  /* get simple 8-bit checksum */
  1030. X
  1031. X                    if (inchecksum == checksum) /* good checksum, hence good packet */
  1032. X                    {  
  1033. X                        xmdebug("checksum ok");
  1034. X                        errors = 0;
  1035. X                        recvsectcnt += (bufsize == 128) ? 1 : 8;
  1036. X                        nocancanabort = CANCAN ? FALSE : TRUE;
  1037. X                        sectnum = sectcurr; 
  1038. X
  1039. X                        if (!openflag)      /* open output file if necessary */
  1040. X                        {
  1041. X                            openflag = TRUE;
  1042. X                            if ((fd = creat(name, CREATMODE)) < 0)
  1043. X                            {
  1044. X                                sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1045. X                                error("Can't create file for receive", TRUE);
  1046. X                            }
  1047. X                            if (!BATCH)
  1048. X                                {
  1049. X                                logitarg("File Name: %s\n", name);
  1050. X                                tlogitarg("File Name: %s\n", name);
  1051. X                                }
  1052. X                        }
  1053. X
  1054. X                        if (write(fd, (char *) buff, bufctr) != bufctr)
  1055. X                        {
  1056. X                            close(fd);
  1057. X                            unlink(name);
  1058. X                            error("File Write Error", TRUE);
  1059. X                        }
  1060. X                        else
  1061. X                        {
  1062. X                            if (TIPFLAG && recvsectcnt % 32 == 0)
  1063. X                                tlogitarg("Sector %s received\n", sectdisp(recvsectcnt,bufsize,0));
  1064. X                            if (!YMODEMG)
  1065. X                                {
  1066. X                                flushin();          /* flush input */
  1067. X                                sendbyte(ACK);      /* ACK the received packet */
  1068. X                                }
  1069. X                        }
  1070. X                    }
  1071. X
  1072. X                    /* Start handling various errors and special conditions */
  1073. X
  1074. X                    else        /* bad checksum */
  1075. X                    {  
  1076. X                        logitarg("Checksum Error on Sector %s:  ", sectdisp(recvsectcnt,bufsize,1));
  1077. X                        logitarg("sent=%x  ", inchecksum);
  1078. X                        logitarg("recvd=%x\n", checksum);
  1079. X                        tlogitarg("Checksum Error on Sector %s:  ", sectdisp(recvsectcnt,bufsize,1));
  1080. X                        tlogitarg("sent=%x  ", inchecksum);
  1081. X                        tlogitarg("recvd=%x\n", checksum);
  1082. X                        fileread = readbackup;
  1083. X                        errorflag = TRUE;
  1084. X                        if (YMODEMG)
  1085. X                            fatalerror = TRUE;
  1086. X                    }
  1087. X                }
  1088. X
  1089. X                else    /* read timeout */
  1090. X                {
  1091. X                    logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
  1092. X                    tlogitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
  1093. X                    fileread = readbackup;
  1094. X                    errorflag = TRUE;
  1095. X                    if (YMODEMG)
  1096. X                        fatalerror = TRUE;
  1097. X                }
  1098. X            }
  1099. X
  1100. X            else        /* sector number is wrong OR Ymodem filename */
  1101. X            { 
  1102. X                if (sectcurr == 0 && recvsectcnt == 0)  /* Ymodem file-name packet */
  1103. X                {
  1104. X                    logit("YMODEM Batch Protocol\n");
  1105. X                    tlogit("YMODEM Batch Protocol\n");
  1106. X
  1107. X                    /* Read and process a file-name packet */
  1108. X
  1109. X                    if (readbuf(bufsize, 1, FALSE, FALSE, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
  1110. X                    {
  1111. X
  1112. X                        /* verify checksum or CRC */
  1113. X
  1114. X                        if (CRCMODE) 
  1115. X                        {
  1116. X                            checksum &= 0xffff;
  1117. X                            inchecksum = readbyte(3);  /* get 16-bit CRC */
  1118. X                            inchecksum = (inchecksum<<8) | readbyte(3);
  1119. X                        }
  1120. X
  1121. X                        else
  1122. X                            inchecksum = readbyte(3);  /* get simple 8-bit checksum */
  1123. X
  1124. X                        if (inchecksum == checksum) /* good checksum, hence good filename */
  1125. X                        {
  1126. X                            xmdebug("checksum ok");
  1127. X                            strcpy(name, (char *)buff);
  1128. X                            expsect = ((buff[bufsize-1]<<8) | buff[bufsize-2]);
  1129. X                            BATCH = TRUE;
  1130. X                            YMDMBAT = TRUE;
  1131. X                            if (strlen(name) == 0)  /* check for no more files */
  1132. X                            {
  1133. X                                flushin();          /* flush input */
  1134. X                                sendbyte(ACK);      /* ACK the packet */
  1135. X                                logit("YMODEM Batch Receive Complete\n");
  1136. X                                tlogit("YMODEM Batch Receive Complete\n");
  1137. X                                return (FALSE);
  1138. X                            }
  1139. X                            unixify(name);       /* make filename canonical */
  1140. X
  1141. X                            /* read rest of YMODEM header */
  1142. X                            p = (char *)buff + strlen((char *)buff) + 1;
  1143. X                            if (DEBUG)
  1144. X                                fprintf(LOGFP, "DEBUG: header info: %s\n", p);
  1145. X                            sscanf(p, "%ld%lo%o%o%d%ld%d", 
  1146. X                              &filelength, &modtime, &filemode, 
  1147. X                              &serial, &filesleft, &totalleft,
  1148. X                              &yfiletype);
  1149. X                            logitarg("YMODEM file name: %s\n", name);
  1150. X                            tlogitarg("YMODEM file name: %s\n", name);
  1151. X                            fileread = 0l;
  1152. X                            if (filelength)
  1153. X                            {
  1154. X                                CHECKLENGTH = TRUE;
  1155. X                                logitarg("YMODEM file size: %ld\n", filelength);
  1156. X                                tlogitarg("YMODEM file size: %ld\n", filelength);
  1157. X                            }
  1158. X                            else if (expsect)
  1159. X                                logitarg("YMODEM estimated file length %d sectors\n", expsect);
  1160. X                            if (modtime)
  1161. X                            {
  1162. X                                logitarg("YMODEM file date: %s", ctime((time_t *)&modtime));
  1163. X                            }
  1164. X                            if (filemode)
  1165. X                                logitarg("YMODEM file mode: %o\n", filemode);
  1166. X
  1167. X                            if (filesleft)
  1168. X                            {
  1169. X                                logitarg("YMODEM %d file(s) left to receive ", filesleft);
  1170. X                                logitarg("containing %ld bytes\n", totalleft);
  1171. X                                tlogitarg("YMODEM %d file(s) left to receive ", filesleft);
  1172. X                                tlogitarg("containing %ld bytes\n", totalleft);
  1173. X                            }
  1174. X                            if (serial)
  1175. X                                logitarg("YMODEM sender's serial number: %d\n", serial);
  1176. X                            if (yfiletype)
  1177. X                                logitarg("YMODEM file type %d\n", yfiletype);
  1178. X
  1179. X                            openflag = TRUE;    /* open the file for writing */
  1180. X                            if ((fd = creat(name, CREATMODE)) < 0)
  1181. X                            {
  1182. X                                sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1183. X                                error("Can't create file for receive", TRUE);
  1184. X                            }
  1185. X                            if (!YMODEMG)
  1186. X                                {
  1187. X                                flushin();        /* flush the input stream */
  1188. X                                sendbyte(ACK);        /* ACK the filename packet */
  1189. X                                }
  1190. X                            /* do initial handshake to start file transfer */
  1191. X                            if (YMODEMG)
  1192. X                                sendbyte(GCHR);
  1193. X                            else if (CRCMODE) 
  1194. X                            {
  1195. X                                sendbyte(CRCCHR);
  1196. X                                if (LONGPACK)
  1197. X                                    sendbyte(KCHR);
  1198. X                            }
  1199. X                            else
  1200. X                                sendbyte(NAK);
  1201. X                            firstwait = WAITFIRST;  /* reset waiting time */
  1202. X                        }
  1203. X
  1204. X                        else                /* bad filename checksum */
  1205. X                        {
  1206. X                            logit("checksum error on filename sector\n");
  1207. X                            tlogit("checksum error on filename sector\n");
  1208. X                            errorflag = TRUE;
  1209. X                            if (YMODEMG)
  1210. X                                fatalerror = TRUE;
  1211. X                        }
  1212. X                    }
  1213. X                    else
  1214. X                    {
  1215. X                        logit("Timeout while reading filename packet\n");
  1216. X                        tlogit("Timeout while reading filename packet\n");
  1217. X                        errorflag = TRUE;
  1218. X                        if (YMODEMG)
  1219. X                            fatalerror = TRUE;
  1220. X                    }
  1221. X                }
  1222. X
  1223. X                else if (sectcurr == sectnum)   /* duplicate sector? */
  1224. X                {  
  1225. X                    logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
  1226. X                    tlogitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
  1227. X                    if (YMODEMG)
  1228. X                        {
  1229. X                        errorflag = TRUE;
  1230. X                        fatalerror = TRUE;
  1231. X                        }
  1232. X                    else
  1233. X                        {
  1234. X                        flushin();                  /* REALLY flush input */
  1235. X                        while(readbyte(1) != TIMEOUT)
  1236. X                            ;
  1237. X                        sendbyte(ACK);
  1238. X                        }
  1239. X                }
  1240. X                else                /* no, real phase error */
  1241. X                {
  1242. X                    logitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
  1243. X                    tlogitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
  1244. X                    errorflag = TRUE;
  1245. X                    fatalerror = TRUE;
  1246. X                }
  1247. X            }
  1248. X        }
  1249. X
  1250. X        else        /* bad packet number checksum */
  1251. X        {  
  1252. X            logitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
  1253. X            tlogitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
  1254. X            errorflag = TRUE;
  1255. X            if (YMODEMG)
  1256. X                fatalerror = TRUE;
  1257. X        }
  1258. X
  1259. X    }           /* END reading packet loop */
  1260. X
  1261. X    if (errorflag && !fatalerror && recvsectcnt != 0)   /* Handle errors */
  1262. X    {  
  1263. X        errors++;
  1264. X
  1265. X        if (errors >= ERRORMAX)     /* over error limit? */
  1266. X            fatalerror = TRUE;
  1267. X        else                        /* flush input and NAK the packet */
  1268. X        {
  1269. X            flushin();
  1270. X            while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
  1271. X                ;
  1272. X            sendbyte(NAK);
  1273. X        }
  1274. X    }
  1275. X
  1276. X    if (recvsectcnt == 0 && errorflag && !fatalerror && firstchar != EOT)     /* handle startup handshake */
  1277. X    {
  1278. X        sterrors++;
  1279. X
  1280. X        if (sterrors >= STERRORMAX)
  1281. X            fatalerror = TRUE;
  1282. X
  1283. X        else if (CRCMODE && MDM7BAT && !BATCH)
  1284. X            sendbyte(NAK);
  1285. X        
  1286. X        else if (CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
  1287. X        {
  1288. X            CRCMODE = FALSE;
  1289. X            logit("Sender not accepting CRC request, changing to checksum\n");
  1290. X            tlogit("Sender not accepting CRC request, changing to checksum\n");
  1291. X            sendbyte(NAK);
  1292. X        }
  1293. X
  1294. X        else if (!CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
  1295. X        {
  1296. X            CRCMODE = TRUE;
  1297. X            logit("Sender not accepting checksum request, changing to CRC\n");
  1298. X            tlogit("Sender not accepting checksum request, changing to CRC\n");
  1299. X            sendbyte(CRCCHR);
  1300. X            if (LONGPACK && !MDM7BAT)
  1301. X                sendbyte(KCHR);
  1302. X        }
  1303. X
  1304. X        else if (YMODEMG)
  1305. X            sendbyte(GCHR);
  1306. X
  1307. X        else if (CRCMODE)
  1308. X            {
  1309. X            sendbyte(CRCCHR);
  1310. X            if (LONGPACK && !MDM7BAT)
  1311. X                sendbyte(KCHR);
  1312. X            }
  1313. X
  1314. X        else
  1315. X            sendbyte(NAK);
  1316. X    }
  1317. X}
  1318. Xwhile ((firstchar != EOT) && !fatalerror);   /* end of MAIN Do-While */
  1319. X
  1320. Xif ((firstchar == EOT) && !fatalerror)  /* normal exit? */
  1321. X{
  1322. X    if (openflag)       /* close the file */
  1323. X        close(fd);
  1324. X    sendbyte(ACK);      /* ACK the EOT */
  1325. X    logit("Receive Complete\n");
  1326. X    tlogit("Receive Complete\n");
  1327. X    if (LOGFLAG)
  1328. X        prtime (recvsectcnt, time((time_t *) 0) - start, LOGFP);
  1329. X    if (TIPFLAG)
  1330. X        prtime (recvsectcnt, time((time_t *) 0) - start, stderr);
  1331. X
  1332. X    if (openflag && modtime)   /* set file modification time */
  1333. X    {
  1334. X        timep[0] = time((time_t *) 0);
  1335. X        timep[1] = modtime;
  1336. X        utime(name, timep);
  1337. X    }
  1338. X
  1339. X    if (BATCH)          /* send appropriate return code */
  1340. X        return(TRUE);
  1341. X    else
  1342. X        return(FALSE);
  1343. X}
  1344. Xelse                /* no, error exit */
  1345. X{ 
  1346. X    if (openflag)
  1347. X    {
  1348. X        sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1349. X        close(fd);
  1350. X        unlink(name);
  1351. X        flushin();
  1352. X        while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
  1353. X            ;
  1354. X        error("ABORTED -- Too Many Errors -- Deleting File", TRUE);
  1355. X    }
  1356. X    else if (recvsectcnt != 0)
  1357. X        {
  1358. X        sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1359. X        flushin();
  1360. X        while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
  1361. X            ;
  1362. X        error("ABORTED -- Too Many Errors", TRUE);
  1363. X        }
  1364. X    else
  1365. X        {
  1366. X        flushin();
  1367. X        while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
  1368. X            ;
  1369. X        error("ABORTED -- Remote system is not responding", TRUE);
  1370. X        }
  1371. X
  1372. X}
  1373. X
  1374. Xreturn(FALSE);
  1375. X}
  1376. END_OF_FILE
  1377.   if test 17709 -ne `wc -c <'receive.c'`; then
  1378.     echo shar: \"'receive.c'\" unpacked with wrong size!
  1379.   fi
  1380.   # end of 'receive.c'
  1381. fi
  1382. if test -f 'xmodem.c' -a "${1}" != "-c" ; then 
  1383.   echo shar: Will not clobber existing file \"'xmodem.c'\"
  1384. else
  1385.   echo shar: Extracting \"'xmodem.c'\" \(8438 characters\)
  1386.   sed "s/^X//" >'xmodem.c' <<'END_OF_FILE'
  1387. X/*
  1388. X *  XMODEM -- Implements the Christensen XMODEM protocol, 
  1389. X *            for packetized file up/downloading.    
  1390. X *
  1391. X *    See the README file for some notes on SYS V adaptations.
  1392. X *    The program has been successfully run on VAXes (4.3BSD) and SUN-3/4s
  1393. X *    (SunOS 3.x) against MEX-PC and ZCOMM/DSZ.
  1394. X *
  1395. X *  See the README and update.doc files for history and change notes.
  1396. X *
  1397. X *  Please send bug fixes, additions and comments to:
  1398. X *    grandi@noao.edu
  1399. X */
  1400. X
  1401. X#include "xmodem.h"
  1402. X
  1403. Xmain(argc, argv)
  1404. Xint argc;
  1405. Xchar **argv;
  1406. X{
  1407. X    char *getenv();
  1408. X    FILE *fopen();
  1409. X    char *unix_cpm();
  1410. X    char *strcpy();
  1411. X    char *strcat();
  1412. X    char *prtype();
  1413. X    
  1414. X    char *fname = filename;        /* convenient place to stash file names */
  1415. X    char *logfile = "xmodem.log";    /* Name of LOG File */
  1416. X    
  1417. X    char *stamptime();        /* for timestamp */
  1418. X
  1419. X    char *defname = "xmodem.in";    /* default file name if none given */
  1420. X
  1421. X    struct stat filestatbuf;    /* file status info */
  1422. X
  1423. X    int index;
  1424. X    char flag;
  1425. X    long expsect;
  1426. X    int fd;
  1427. X
  1428. X    /* initialize option flags */
  1429. X
  1430. X    XMITTYPE = 't';        /* assume text transfer */
  1431. X    DEBUG = FALSE;        /* keep debugging info in log */
  1432. X    RECVFLAG = FALSE;    /* not receive */
  1433. X    SENDFLAG = FALSE;    /* not send either */
  1434. X    BATCH = FALSE;        /* nor batch */
  1435. X    CRCMODE = FALSE;    /* use checksums for now */
  1436. X    DELFLAG = FALSE;    /* don't delete old log file */
  1437. X    LOGFLAG = TRUE;        /* keep log */
  1438. X    LONGPACK = FALSE;     /* do not use long packets on transmit */
  1439. X    MDM7BAT = FALSE;    /* no MODEM7 batch mode */
  1440. X    YMDMBAT = FALSE;    /* no YMODEM batch mode */
  1441. X    TOOBUSY = FALSE;    /* not too busy for sleeping in packet read */
  1442. X    TIPFLAG = FALSE;    /* no special logging on stderr */
  1443. X    DELAYFLAG = FALSE;    /* don't delay startup for a while */
  1444. X    NOEOT = FALSE;        /* don't suppress EOT verification */
  1445. X    CANCAN = FALSE;        /* don't allow CAN-CAN aborts in mid-transfer */
  1446. X    YMODEMG = FALSE;    /* no YMODEM-G */
  1447. X
  1448. X    fprintf(stderr, "XMODEM Version %s", VERSION);
  1449. X    fprintf(stderr, " -- UNIX-Microcomputer File Transfer Facility\n");
  1450. X
  1451. X    if (argc == 1)
  1452. X        {
  1453. X        help();
  1454. X        exit(-1);
  1455. X        }
  1456. X
  1457. X    index = 0;        /* set index for flag loop */
  1458. X
  1459. X    stopsig();        /* suppress keyboard stop signal */
  1460. X
  1461. X    while ((flag = argv[1][index++]) != '\0')
  1462. X        switch (flag) {
  1463. X        case '-' : break;
  1464. X        case 'X' :
  1465. X        case 'x' : DEBUG = TRUE;  /* turn on debugging log */
  1466. X               break;
  1467. X        case 'C' :
  1468. X        case 'c' : CRCMODE = TRUE; /* enable CRC on receive */
  1469. X               break;
  1470. X        case 'D' :
  1471. X        case 'd' : DELFLAG = TRUE;  /* delete log file */
  1472. X               break;
  1473. X        case 'L' :
  1474. X        case 'l' : LOGFLAG = FALSE;  /* turn off log  */
  1475. X               break;
  1476. X        case 'm' :
  1477. X        case 'M' : MDM7BAT = TRUE;  /* turn on MODEM7 batch protocol */
  1478. X               BATCH   = TRUE;
  1479. X               break;
  1480. X        case 'y' :
  1481. X        case 'Y' : YMDMBAT = TRUE;  /* turn on YMODEM batch protocol */
  1482. X               BATCH   = TRUE;
  1483. X               break;
  1484. X        case 'k' :
  1485. X        case 'K' : LONGPACK = TRUE;  /* use 1K packets on transmit */
  1486. X               break;
  1487. X        case 't' :
  1488. X        case 'T' : TOOBUSY = TRUE;  /* turn off sleeping */
  1489. X               break;
  1490. X        case 'p' :
  1491. X        case 'P' : TIPFLAG = TRUE;  /* turn on special handling for SunOS tip */
  1492. X               break;
  1493. X        case 'w' :
  1494. X        case 'W' : DELAYFLAG = TRUE;  /* delay startup */
  1495. X               break;
  1496. X        case 'e' :
  1497. X        case 'E' : NOEOT = TRUE;  /* turn off EOT verification */
  1498. X               break;
  1499. X        case 'n' :
  1500. X        case 'N' : CANCAN = TRUE;  /* allow mid-transfer CAN-CAN */
  1501. X               break;
  1502. X        case 'g' :
  1503. X        case 'G' : YMODEMG = TRUE;  /* YMODEM-G mode */
  1504. X               CANCAN = TRUE;
  1505. X               CRCMODE = TRUE;
  1506. X               YMDMBAT = TRUE;
  1507. X               break;
  1508. X        case 'R' :
  1509. X        case 'r' : RECVFLAG = TRUE;  /* receive file */
  1510. X               XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
  1511. X               break;
  1512. X        case 'S' :
  1513. X        case 's' : SENDFLAG = TRUE;  /* send file */
  1514. X               XMITTYPE = gettype(argv[1][index++]);
  1515. X               break;
  1516. X        default  : fprintf(stderr, "Invalid Flag %c ignored\n", flag);
  1517. X               break;
  1518. X       }
  1519. X
  1520. X    if (DEBUG)
  1521. X        LOGFLAG = TRUE;
  1522. X
  1523. X    if (LOGFLAG)
  1524. X       { 
  1525. X         if ((fname = getenv("HOME")) == 0)    /* Get HOME variable */
  1526. X        error("XMODEM Fatal Error- Can't get Environment!", FALSE);
  1527. X         fname = strcat(fname, "/");
  1528. X         fname = strcat(fname, logfile);
  1529. X         if (!DELFLAG)
  1530. X        LOGFP = fopen(fname, "a");  /* append to LOG file */
  1531. X         else
  1532. X        LOGFP = fopen(fname, "w");  /* new LOG file */
  1533. X         if (!LOGFP)
  1534. X        error("XMODEM Fatal Error- Can't Open Log File", FALSE);
  1535. X
  1536. X         fprintf(LOGFP,"\n++++++++  %s", stamptime());
  1537. X         fprintf(LOGFP,"XMODEM Version %s\n", VERSION);
  1538. X         fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
  1539. X         for (index=2; index<argc; ++index)
  1540. X        fprintf(LOGFP, " %s", argv[index]);
  1541. X         fprintf(LOGFP, "\n");
  1542. X       }
  1543. X
  1544. X    getspeed();        /* get tty-speed for time estimates */
  1545. X
  1546. X    if (RECVFLAG && SENDFLAG)
  1547. X        error("XMODEM Fatal Error- Both Send and Receive Functions Specified", FALSE);
  1548. X
  1549. X    if (MDM7BAT && (YMDMBAT || YMODEMG))
  1550. X        error("XMODEM Fatal Error - Both YMODEM and MODEM7 Batch Protocols Specified", FALSE);
  1551. X
  1552. X    if (!RECVFLAG && !SENDFLAG)
  1553. X        error("XMODEM Fatal Error - Either Send or Receive Function must be chosen!",FALSE);
  1554. X    
  1555. X    if (SENDFLAG && argc==2)
  1556. X        error("XMODEM Fatal Error - No file specified to send",FALSE);
  1557. X
  1558. X    if (RECVFLAG && argc==2)
  1559. X        {
  1560. X        /* assume we really want CRC-16 in batch, unless we specify MODEM7 mode, unless we explicitly set CRCMODE */ 
  1561. X        if (!CRCMODE)
  1562. X            CRCMODE = MDM7BAT ? FALSE : TRUE;
  1563. X        fprintf(stderr, "Ready for BATCH RECEIVE");
  1564. X        fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  1565. X        if (!TIPFLAG)
  1566. X            fprintf(stderr, "Send several Control-X characters to cancel\n");
  1567. X        logit("Batch Receive Started");
  1568. X        logitarg(" in %s mode\n", prtype(XMITTYPE));
  1569. X        strcpy(fname, defname);
  1570. X        }
  1571. X
  1572. X    if (RECVFLAG && argc>2)
  1573. X        {
  1574. X        if(open(argv[2], 0) != -1)  /* check for overwriting */
  1575. X            {
  1576. X            logit("Warning -- Target File Exists and is Being Overwritten\n");
  1577. X            fprintf(stderr, "Warning -- Target File Exists and is Being Overwritten\n");
  1578. X            }
  1579. X        fprintf(stderr, "Ready to RECEIVE File %s", argv[2]);
  1580. X        fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  1581. X        if (!TIPFLAG)
  1582. X            fprintf(stderr, "Send several Control-X characters to cancel\n");
  1583. X        logitarg("Receiving in %s mode\n", prtype(XMITTYPE));
  1584. X        strcpy(fname,argv[2]);
  1585. X        }
  1586. X
  1587. X    if (RECVFLAG)
  1588. X        {  
  1589. X        if (DELAYFLAG)        /* delay if -w requested */
  1590. X            sleep(TIPDELAY);
  1591. X        setmodes();        /* set tty modes for transfer */
  1592. X
  1593. X        while(rfile(fname) != FALSE);  /* receive files */
  1594. X
  1595. X        flushin();
  1596. X        restoremodes(FALSE);    /* restore normal tty modes */
  1597. X
  1598. X        sleep(2);        /* give other side time to return to terminal mode */
  1599. X        exit(0);
  1600. X        }
  1601. X
  1602. X    if (SENDFLAG && BATCH) 
  1603. X        {
  1604. X        if (YMDMBAT)
  1605. X            {
  1606. X            ytotleft = 0l;
  1607. X            yfilesleft = 0;
  1608. X            for (index=2; index<argc; index++) {
  1609. X                if (stat(argv[index], &filestatbuf) == 0) {
  1610. X                    yfilesleft++;
  1611. X                    ytotleft += filestatbuf.st_size;
  1612. X                    if (XMITTYPE == 't') {
  1613. X                        if((fd=open(argv[index],0)) >= 0) {
  1614. X                            ytotleft += countnl(fd);
  1615. X                            close(fd);
  1616. X                            }
  1617. X                        }
  1618. X                    }
  1619. X                }
  1620. X            if (DEBUG)
  1621. X                fprintf(LOGFP, "DEBUG YMODEM file count: %d, %ld bytes\n", yfilesleft, ytotleft);
  1622. X
  1623. X            fprintf(stderr, "Ready to YMODEM BATCH SEND");
  1624. X            fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  1625. X            logit("YMODEM Batch Send Started");
  1626. X            logitarg(" in %s mode\n", prtype(XMITTYPE));
  1627. X            }
  1628. X        else if (MDM7BAT)
  1629. X            {
  1630. X            fprintf(stderr, "Ready to MODEM7 BATCH SEND");
  1631. X            fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  1632. X            logit("MODEM7 Batch Send Started");
  1633. X            logitarg(" in %s mode\n", prtype(XMITTYPE));
  1634. X            }
  1635. X        if (!TIPFLAG)
  1636. X            fprintf(stderr, "Send several Control-X characters to cancel\n");
  1637. X
  1638. X        if (DELAYFLAG)        /* delay if -w requested */
  1639. X            sleep(TIPDELAY);
  1640. X        setmodes();
  1641. X        for (index=2; index<argc; index++) {
  1642. X            if (stat(argv[index], &filestatbuf) < 0) {
  1643. X                logitarg("\nFile %s not found\n", argv[index]);
  1644. X                tlogitarg("\nFile %s not found\n", argv[index]);
  1645. X                continue;
  1646. X            }
  1647. X            sfile(argv[index]);
  1648. X        }
  1649. X        sfile("");
  1650. X        flushin();
  1651. X        restoremodes(FALSE);
  1652. X
  1653. X        logit("Batch Send Complete\n");
  1654. X        tlogit("Batch Send Complete\n");
  1655. X        sleep(2);
  1656. X        exit (0);
  1657. X        }
  1658. X
  1659. X    if (SENDFLAG && !BATCH) 
  1660. X        {
  1661. X        if (stat(argv[2], &filestatbuf) < 0)
  1662. X            error("Can't find requested file", FALSE);
  1663. X        expsect = (filestatbuf.st_size/128)+1;
  1664. X            
  1665. X        fprintf(stderr, "File %s Ready to SEND", argv[2]);
  1666. X        fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  1667. X        fprintf(stderr, "Estimated File Size %ldK, %ld Sectors, %ld Bytes\n",
  1668. X              (filestatbuf.st_size/1024)+1, expsect,
  1669. X            filestatbuf.st_size);
  1670. X        projtime(expsect, stdout);
  1671. X        if (!TIPFLAG)
  1672. X            fprintf(stderr, "Send several Control-X characters to cancel\n");
  1673. X        logitarg("Sending in %s mode\n", prtype(XMITTYPE));
  1674. X
  1675. X        setmodes();
  1676. X        sfile(argv[2]);
  1677. X        flushin();
  1678. X        restoremodes(FALSE);
  1679. X
  1680. X        sleep(2);
  1681. X        exit(0);
  1682. X        }
  1683. X}
  1684. END_OF_FILE
  1685.   if test 8438 -ne `wc -c <'xmodem.c'`; then
  1686.     echo shar: \"'xmodem.c'\" unpacked with wrong size!
  1687.   fi
  1688.   # end of 'xmodem.c'
  1689. fi
  1690. echo shar: End of archive 1 \(of 3\).
  1691. cp /dev/null ark1isdone
  1692. MISSING=""
  1693. for I in 1 2 3 ; do
  1694.     if test ! -f ark${I}isdone ; then
  1695.     MISSING="${MISSING} ${I}"
  1696.     fi
  1697. done
  1698. if test "${MISSING}" = "" ; then
  1699.     echo You have unpacked all 3 archives.
  1700.     rm -f ark[1-9]isdone
  1701. else
  1702.     echo You still must unpack the following archives:
  1703.     echo "        " ${MISSING}
  1704. fi
  1705. exit 0
  1706. exit 0 # Just in case...
  1707.